package com.example.blogapi.controller;

import com.example.blogapi.model.Blog;
import com.example.blogapi.service.BlogService;
import com.example.blogapi.util.HttpUtil;
import com.example.blogapi.util.JsonUtil;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;

import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class BlogController implements HttpHandler {
    private final BlogService blogService;
    private final ObjectMapper objectMapper;

    public BlogController() {
        this.blogService = new BlogService();
        this.objectMapper = new ObjectMapper();
    }

    @Override
    public void handle(HttpExchange exchange) throws IOException {
        String method = exchange.getRequestMethod();
        String path = exchange.getRequestURI().getPath();

        try {
            if (method.equals("OPTIONS")) {
                handleOptionsRequest(exchange);
            } else if (method.equals("GET") && path.matches("/api/blogs/?")) {
                handleGetAllBlogs(exchange);
            } else if (method.equals("GET") && path.matches("/api/blogs/\\d+/?")) {
                handleGetBlogById(exchange);
            } else if (method.equals("GET") && path.matches("/api/blogs/user/\\d+/?")) {
                handleGetBlogsByUserId(exchange);
            } else if (method.equals("GET") && path.matches("/api/blogs/category/\\d+/?")) {
                handleGetBlogsByCategoryId(exchange);
            } else if (method.equals("GET") && path.matches("/api/blogs/tag/\\d+/?")) {
                handleGetBlogsByTagId(exchange);
            } else if (method.equals("POST") && path.matches("/api/blogs/?")) {
                handleCreateBlog(exchange);
            } else if (method.equals("PUT") && path.matches("/api/blogs/\\d+/?")) {
                handleUpdateBlog(exchange);
            } else if (method.equals("DELETE") && path.matches("/api/blogs/\\d+/?")) {
                handleDeleteBlog(exchange);
            } else {
                String response = JsonUtil.toJson(Map.of("error", "Not found"));
                HttpUtil.sendResponse(exchange, 404, response);
            }
        } catch (Exception e) {
            e.printStackTrace();
            String response = JsonUtil.toJson(Map.of("error", e.getMessage()));
            HttpUtil.sendResponse(exchange, 500, response);
        }
    }

    private void handleOptionsRequest(HttpExchange exchange) throws IOException {
        HttpUtil.sendResponse(exchange, 200, "");
    }

    private void handleGetAllBlogs(HttpExchange exchange) throws IOException, SQLException {
        List<Blog> blogs = blogService.getAllBlogs();
        String response = JsonUtil.toJson(blogs);
        HttpUtil.sendResponse(exchange, 200, response);
    }

    private void handleGetBlogById(HttpExchange exchange) throws IOException, SQLException {
        Long id = HttpUtil.extractIdFromPath(exchange.getRequestURI().getPath(), "/api/blogs/(\\d+)/?");
        
        Blog blog = blogService.getBlogById(id);
        if (blog != null) {
            String response = JsonUtil.toJson(blog);
            HttpUtil.sendResponse(exchange, 200, response);
        } else {
            String response = JsonUtil.toJson(Map.of("error", "Blog not found"));
            HttpUtil.sendResponse(exchange, 404, response);
        }
    }

    private void handleGetBlogsByUserId(HttpExchange exchange) throws IOException, SQLException {
        Long userId = HttpUtil.extractIdFromPath(exchange.getRequestURI().getPath(), "/api/blogs/user/(\\d+)/?");
        
        try {
            List<Blog> blogs = blogService.getBlogsByUserId(userId);
            String response = JsonUtil.toJson(blogs);
            HttpUtil.sendResponse(exchange, 200, response);
        } catch (IllegalArgumentException e) {
            String response = JsonUtil.toJson(Map.of("error", e.getMessage()));
            HttpUtil.sendResponse(exchange, 400, response);
        }
    }

    private void handleGetBlogsByCategoryId(HttpExchange exchange) throws IOException, SQLException {
        Long categoryId = HttpUtil.extractIdFromPath(exchange.getRequestURI().getPath(), "/api/blogs/category/(\\d+)/?");
        
        try {
            List<Blog> blogs = blogService.getBlogsByCategoryId(categoryId);
            String response = JsonUtil.toJson(blogs);
            HttpUtil.sendResponse(exchange, 200, response);
        } catch (IllegalArgumentException e) {
            String response = JsonUtil.toJson(Map.of("error", e.getMessage()));
            HttpUtil.sendResponse(exchange, 400, response);
        }
    }

    private void handleGetBlogsByTagId(HttpExchange exchange) throws IOException, SQLException {
        Long tagId = HttpUtil.extractIdFromPath(exchange.getRequestURI().getPath(), "/api/blogs/tag/(\\d+)/?");
        
        List<Blog> blogs = blogService.getBlogsByTagId(tagId);
        String response = JsonUtil.toJson(blogs);
        HttpUtil.sendResponse(exchange, 200, response);
    }

    private void handleCreateBlog(HttpExchange exchange) throws IOException, SQLException {
        String requestBody = HttpUtil.getRequestBody(exchange);
        JsonNode rootNode = objectMapper.readTree(requestBody);
        
        Blog blog = objectMapper.treeToValue(rootNode.get("blog"), Blog.class);
        List<Long> tagIds = new ArrayList<>();
        
        if (rootNode.has("tagIds")) {
            tagIds = objectMapper.convertValue(rootNode.get("tagIds"), new TypeReference<List<Long>>() {});
        }
        
        try {
            Blog createdBlog = blogService.createBlog(blog, tagIds);
            String response = JsonUtil.toJson(createdBlog);
            HttpUtil.sendResponse(exchange, 201, response);
        } catch (IllegalArgumentException e) {
            String response = JsonUtil.toJson(Map.of("error", e.getMessage()));
            HttpUtil.sendResponse(exchange, 400, response);
        }
    }

    private void handleUpdateBlog(HttpExchange exchange) throws IOException, SQLException {
        Long id = HttpUtil.extractIdFromPath(exchange.getRequestURI().getPath(), "/api/blogs/(\\d+)/?");
        String requestBody = HttpUtil.getRequestBody(exchange);
        JsonNode rootNode = objectMapper.readTree(requestBody);
        
        Blog blog = objectMapper.treeToValue(rootNode.get("blog"), Blog.class);
        List<Long> tagIds = new ArrayList<>();
        
        if (rootNode.has("tagIds")) {
            tagIds = objectMapper.convertValue(rootNode.get("tagIds"), new TypeReference<List<Long>>() {});
        }
        
        try {
            Blog updatedBlog = blogService.updateBlog(id, blog, tagIds);
            String response = JsonUtil.toJson(updatedBlog);
            HttpUtil.sendResponse(exchange, 200, response);
        } catch (IllegalArgumentException e) {
            String response = JsonUtil.toJson(Map.of("error", e.getMessage()));
            HttpUtil.sendResponse(exchange, 400, response);
        }
    }

    private void handleDeleteBlog(HttpExchange exchange) throws IOException, SQLException {
        Long id = HttpUtil.extractIdFromPath(exchange.getRequestURI().getPath(), "/api/blogs/(\\d+)/?");
        
        try {
            boolean deleted = blogService.deleteBlog(id);
            if (deleted) {
                HttpUtil.sendResponse(exchange, 204, "");
            } else {
                String response = JsonUtil.toJson(Map.of("error", "Failed to delete blog"));
                HttpUtil.sendResponse(exchange, 500, response);
            }
        } catch (IllegalArgumentException e) {
            String response = JsonUtil.toJson(Map.of("error", e.getMessage()));
            HttpUtil.sendResponse(exchange, 400, response);
        }
    }
}